using System;
using Microsoft.Practices.Prism.Events;
using Microsoft.Practices.Prism.ViewModel;
using Microsoft.Practices.Unity;
using Ausy.Silverlight.Survey.Infrastructure.Common;
using System.Collections.ObjectModel;
using Ausy.Silverlight.Survey.QuestionModule.Services;
using Ausy.Silverlight.Survey.QuestionModule.Services.ServiceEventArgs;
using System.Linq;
using Ausy.Silverlight.Survey.Infrastructure.Events;
using Ausy.Silverlight.Survey.Infrastructure.Context;
using Ausy.Silverlight.Survey.QuestionModule.Model;

namespace Ausy.Silverlight.Survey.QuestionModule.ViewParts
{
    /// <summary>
    /// Cette classe représente le Vue Model pour le Questionnaire
    /// </summary>
    public class QuestionnaireViewModel : ViewModel<IQuestionnaireView>, IQuestionnaireViewModel
    {
        #region Private Members

        /// <summary>
        /// Service de gestion des questions
        /// </summary>
        private IQuestionService service;

        #endregion

        #region Title Property
        /// <summary>
        /// Property title
        /// </summary>
        private string title;

        /// <summary>
        /// Property Title
        /// </summary>
        public string Title
        {
            get { return title; }
            set
            {
                if (title != value)
                {
                    title = value;
                    RaisePropertyChanged(() => this.Title);
                }
            }
        }

        #endregion

        #region QuestionViewModelCollection Property
        /// <summary>
        /// Property questionViewModelCollection
        /// </summary>
        private ObservableCollection<IQuestionViewModel> questionViewModelCollection;

        /// <summary>
        /// Property QuestionViewModelCollection
        /// </summary>
        public ObservableCollection<IQuestionViewModel> QuestionViewModelCollection
        {
            get { return questionViewModelCollection; }
            set
            {
                if (questionViewModelCollection != value)
                {
                    questionViewModelCollection = value;
                    RaisePropertyChanged(() => this.QuestionViewModelCollection);
                }
            }
        }

        #endregion

        #region UserQuestionnaire Property

        /// <summary>
        /// Questionnaire remplit par l'utilisateur
        /// </summary>
        public UserQuestionnaire UserQuestionnaire { get; private set; }

        #endregion

        #region Constructor

        /// <summary>
        /// Constructeur par défaut
        /// </summary>
        /// <param name="container">Container Unity pour instanciation des type d'objet</param>
        public QuestionnaireViewModel(IUnityContainer container)
            : base(container)
        {

        }

        #endregion

        #region Initialize Method

        /// <summary>
        /// Cette méthode permet l'initialisation du ViewModel avant que le DataContext soit affecté à la vue
        /// </summary>
        protected override void Initialize()
        {
            // Initialisation des données
            this.QuestionViewModelCollection = new ObservableCollection<IQuestionViewModel>();
            this.UserQuestionnaire = new UserQuestionnaire();
            var context = this.container.Resolve<IApplicationContext>();
            context.QuestionnaireResult = 0;

            // Initialisation des commandes
            this.service = this.container.Resolve<IQuestionService>();
            this.service.GetQuestionnaireByIdentifierCompleted += new EventHandler<Services.ServiceEventArgs.QuestionnaireEventArgs>(this.OnGetQuestionnaireByIdentifierCompleted);
            this.service.GetQuestionnaireByIdentifierAsync(context.CurrentQuestionnaire);
        }

        #endregion

        #region OnGetQuestionnaireByIdentifierCompleted Method

        /// <summary>
        /// Cette méthode permet de gérer l'affichage du questionnaire
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void OnGetQuestionnaireByIdentifierCompleted(object sender, QuestionnaireEventArgs e)
        {
            if (e != null && e.Questionnaire != null)
            {
                this.Title = e.Questionnaire.Title;

                if (e.Questionnaire.QuestionCollection.Count > 0)
                {
                    foreach (var question in e.Questionnaire.QuestionCollection)
                    {
                        var questionViewModel = this.container.Resolve<IQuestionViewModel>();
                        questionViewModel.Load(question);
                        questionViewModel.QuestionValidate += new EventHandler<QuestionEventArgs>(this.OnQuestionViewModelValidate);
                        this.QuestionViewModelCollection.Add(questionViewModel);
                    }

                    // Selection la premiere question
                    this.QuestionViewModelCollection.First(q => q.SelectedQuestion = true);
                }
            }
        }

        #endregion

        #region UpdateUserQuestionnaire Method

        /// <summary>
        /// Cette méthode met à jour la liste des réponses
        /// </summary>
        private void UpdateUserQuestionnaire()
        {
            var context = this.container.Resolve<IApplicationContext>();

            this.UserQuestionnaire.AccountReferenceID = context.AccountIdentifier;
            this.UserQuestionnaire.QuestionnaireReferenceID = context.CurrentQuestionnaire;
            this.UserQuestionnaire.QuestionnaireResponseCollection.Clear();

            foreach (var item in this.QuestionViewModelCollection)
            {
                this.UserQuestionnaire.QuestionnaireResponseCollection.Add(item.Response);
            }

            context.QuestionnaireResult = this.UserQuestionnaire.QuestionnaireResult;
        } 

        #endregion

        #region OnQuestionViewModelValidate Method

        /// <summary>
        /// Cette méthode permet de gérer la validation d'une question et de passer à une autre
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void OnQuestionViewModelValidate(object sender, QuestionEventArgs e)
        {
            var validatedQuestion = sender as QuestionViewModel;
            if (validatedQuestion != null)
            {
                // Desabonnement à l'event
                validatedQuestion.SelectedQuestion = false;
                validatedQuestion.QuestionValidate -= this.OnQuestionViewModelValidate;

                // Récupere l'index et selectionne la question suivante
                var index = this.QuestionViewModelCollection.IndexOf(validatedQuestion);
                if (index >= 0 && index < this.QuestionViewModelCollection.Count - 1)
                {
                    index++;
                    this.QuestionViewModelCollection[index].SelectedQuestion = true;
                }
                else
                {
                    // Si dernière question 
                    if (index == this.QuestionViewModelCollection.Count - 1)
                    {
                        this.OnQuestionnaireCompleteValidate();
                    }

                }
            }
        }

        #endregion

        #region OnQuestionnaireCompleteValidate Method

        /// <summary>
        /// Cette méthode est appelée après que le questionnaire soit terminé d'être rempli pour afficher le résultat
        /// </summary>
        void OnQuestionnaireCompleteValidate()
        {
            // Mise a jour de la reponse
            this.UpdateUserQuestionnaire();

            // Appele le service d'enregistrement
            this.service = this.container.Resolve<IQuestionService>();
            this.service.CreateUserQuestionnaireCompleted += new EventHandler<EventArgs>(this.OnCreateUserQuestionnaireCompletedCompleted);
            this.service.CreateUserQuestionnaireAsync(this.UserQuestionnaire);
        }

        #endregion

        #region OnCreateUserQuestionnaireCompletedCompleted Method

        /// <summary>
        /// Cette méthode permet de gérer le retour de l'enregistrement de la réponse
        /// </summary>
        /// <param name="args"></param>
        void OnCreateUserQuestionnaireCompletedCompleted(object sender, EventArgs e)
        {
            this.service.CreateUserQuestionnaireCompleted -= this.OnCreateUserQuestionnaireCompletedCompleted;

            this.eventAggregator.GetEvent<NavigateEvent>().Publish(new NavigateEvent(NavigateUri.ResultAccountUri));
        } 

        #endregion
    }
}
